import { getLogger } from '@/utils/logger';
import cacheUtils from '@/utils/cache/cache.util';

const logger = getLogger('password-service', {
  console: false
});
const consoleLogger = getLogger('password-service');

// pwd_err_cnt 缓存 key 前缀
const PWD_ERR_CNT_PREFIX = "pwd_err_cnt:";

// 定义常量
const DEFAULT_MAX_RETRY_COUNT = 5; // 默认最大重试次数
const DEFAULT_LOCK_TIME = 10; // 默认锁定时间（分钟）

/**
 * 密码服务，处理登录失败计数和账户锁定
 *
 * 说明：本服务所有缓存key、锁定逻辑、清理逻辑均与RuoYi Java端完全对齐，
 * 采用pwd_err_cnt:{username}为唯一缓存key，兼容Java端监控与清理工具。
 */
class PasswordService {
  private maxRetryCount: number;
  private lockTime: number;

  constructor() {
    this.maxRetryCount = parseInt(process.env.PASSWORD_RETRY_COUNT || '5', 10);
    this.lockTime = parseInt(process.env.PASSWORD_LOCK_TIME || '10', 10);
  }

  /**
   * 获取登录错误次数
   * @param username 用户名
   * @returns 失败次数
   */
  public async getLoginRetryCount(username: string): Promise<number> {
    try {
      // 使用consoleLogger记录操作开始
      consoleLogger.info(`获取登录错误次数: username=${username}`);
      
      if (!username) {
        logger.warn('获取登录错误次数: 用户名为空');
        return 0;
      }
      
      const key = `${PWD_ERR_CNT_PREFIX}${username}`;
      const cacheResult = await cacheUtils.get(key);
      
      let retryCount = 0;
      if (cacheResult.success && cacheResult.data) {
        retryCount = parseInt(cacheResult.data, 10);
        logger.debug(`用户 ${username} 当前登录错误次数: ${retryCount}`);
      }
      
      return retryCount;
    } catch (error) {
      consoleLogger.error(`获取登录错误次数失败: ${error instanceof Error ? error.message : String(error)}`);
      // 发生错误时返回0，避免影响登录流程
      return 0;
    }
  }

  /**
   * 记录登录错误次数
   * @param username 用户名
   * @returns 失败次数
   */
  public async incrementLoginRetryCount(username: string): Promise<number> {
    try {
      // 使用consoleLogger记录操作开始
      consoleLogger.info(`增加登录错误次数: username=${username}`);
      
      if (!username) {
        consoleLogger.error('增加登录错误次数失败: 用户名为空');
        return 0;
      }
      
      const key = `${PWD_ERR_CNT_PREFIX}${username}`;
      const cacheResult = await cacheUtils.incr(key);
      
      let retryCount = 0;
      if (cacheResult.success && typeof cacheResult.data === 'number') {
        retryCount = cacheResult.data;
        
        // 如果是第一次错误，设置过期时间
        if (retryCount === 1) {
          logger.debug(`用户 ${username} 首次登录失败，设置过期时间: ${this.lockTime} 分钟`);
          await cacheUtils.expire(key, this.lockTime * 60);
        }
        
        // 如果达到锁定阈值，记录警告日志
        if (retryCount >= this.maxRetryCount) {
          consoleLogger.warn(`用户 ${username} 密码输入错误次数已达到 ${retryCount} 次，账户已被锁定 ${this.lockTime} 分钟`);
        } else {
          logger.info(`用户 ${username} 密码输入错误次数: ${retryCount}`);
        }
      } else {
        logger.error(`增加登录错误次数缓存操作失败: ${cacheResult.error?.message || cacheResult.error || '未知错误'}`);
      }
      
      return retryCount;
    } catch (error) {
      consoleLogger.error(`增加登录错误次数失败: ${error instanceof Error ? error.message : String(error)}`);
      return 0;
    }
  }

  /**
   * 清除登录错误次数
   * @param username 用户名
   */
  public async clearLoginRetryCount(username: string): Promise<void> {
    try {
      // 使用consoleLogger记录操作开始
      consoleLogger.info(`清除登录错误次数: username=${username}`);
      
      if (!username) {
        logger.warn('清除登录错误次数: 用户名为空');
        return;
      }
      
      const key = `${PWD_ERR_CNT_PREFIX}${username}`;
      const cacheResult = await cacheUtils.del(key);
      
      if (cacheResult.success) {
        logger.info(`已清除用户 ${username} 的登录错误次数缓存`);
      } else {
        logger.error(`清除登录错误次数缓存失败: ${cacheResult.error?.message || cacheResult.error || '未知错误'}`);
      }
    } catch (error) {
      consoleLogger.error(`清除登录错误次数失败: ${error instanceof Error ? error.message : String(error)}`);
    }
  }

  /**
   * 登录失败，处理账户锁定逻辑
   * @param username 用户名
   * @returns 用户是否被锁定
   */
  public async loginFail(username: string): Promise<boolean> {
    try {
      // 使用consoleLogger记录操作开始
      consoleLogger.info(`处理登录失败: username=${username}`);
      
      if (!username) {
        consoleLogger.error('处理登录失败: 用户名为空');
        return false;
      }
      
      const retryCount = await this.incrementLoginRetryCount(username);
      const isLocked = retryCount >= this.maxRetryCount;
      
      if (isLocked) {
        consoleLogger.warn(`用户 ${username} 密码输入错误次数已达到 ${retryCount} 次，账户已被锁定 ${this.lockTime} 分钟`);
      } else {
        logger.info(`用户 ${username} 登录失败，当前错误次数: ${retryCount}/${this.maxRetryCount}`);
      }
      
      return isLocked;
    } catch (error) {
      consoleLogger.error(`处理登录失败操作异常: ${error instanceof Error ? error.message : String(error)}`);
      return false;
    }
  }

  /**
   * 登录成功，清除失败记录
   * @param username 用户名
   */
  public async loginSuccess(username: string): Promise<void> {
    try {
      // 使用consoleLogger记录操作开始
      consoleLogger.info(`处理登录成功: username=${username}`);
      
      if (!username) {
        logger.warn('处理登录成功: 用户名为空');
        return;
      }
      
      await this.clearLoginRetryCount(username);
      logger.info(`用户 ${username} 登录成功，已清除错误次数记录`);
    } catch (error) {
      consoleLogger.error(`处理登录成功操作异常: ${error instanceof Error ? error.message : String(error)}`);
    }
  }

  /**
   * 验证用户账户是否被锁定
   * @param username 用户名
   * @returns 是否锁定
   */
  public async isAccountLocked(username: string): Promise<boolean> {
    try {
      // 使用consoleLogger记录操作开始
      consoleLogger.info(`检查账户是否锁定: username=${username}`);
      
      if (!username) {
        logger.warn('检查账户是否锁定: 用户名为空');
        return false;
      }
      
      const retryCount = await this.getLoginRetryCount(username);
      const isLocked = retryCount >= this.maxRetryCount;
      
      if (isLocked) {
        consoleLogger.warn(`用户 ${username} 账户已被锁定，当前错误次数: ${retryCount}/${this.maxRetryCount}`);
      } else {
        logger.debug(`用户 ${username} 账户未锁定，当前错误次数: ${retryCount}/${this.maxRetryCount}`);
      }
      
      return isLocked;
    } catch (error) {
      consoleLogger.error(`检查账户锁定状态异常: ${error instanceof Error ? error.message : String(error)}`);
      return false;
    }
  }
}

export default new PasswordService(); 